package com.gaogzhen.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author Administrator
 */
@Slf4j(topic = "c.TestReadWriteLock")
public class TestReadWriteLock {
    public static void main(String[] args) {
        DataContainer dataContainer = new DataContainer();
//        new Thread(() -> {
//            dataContainer.read();
//        }, "t1").start();
//
//
//        new Thread(() -> {
//            dataContainer.write();
//        }, "t2").start();

        new Thread(() -> {
            dataContainer.writeRead();
        }, "t3").start();
    }
}

@Slf4j(topic = "c.DataContainer")
class DataContainer {
    private Object data;
    private ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
    private ReentrantReadWriteLock.ReadLock r = rw.readLock();
    private ReentrantReadWriteLock.WriteLock w = rw.writeLock();

    public Object read() {
         log.debug("获取读锁...");
         r.lock();
         try {
             log.debug("读取。。。");
             TimeUnit.SECONDS.sleep(1);

         } catch (InterruptedException e) {
             e.printStackTrace();
         } finally {
             log.debug("释放读锁。。。");
             r.unlock();
             return data;
         }
    }

    public void write() {
        log.debug("获取写锁...");
        w.lock();
        try {
            log.debug("写数据。。。");
            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log.debug("释放写锁。。。");
            w.unlock();
        }
    }

    public void readWrite() {
        log.debug("获取读锁...");
        r.lock();
        try {
            log.debug("获取写锁...");
            try {
                w.lock();
                log.debug("写数据。。。");
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                w.unlock();
            }

        } finally {
            log.debug("释放读锁。。。");
            r.unlock();
        }
    }

    public Object writeRead() {
        log.debug("获取写锁...");
        w.lock();
        try {
            try {
                log.debug("获取读锁...");
                r.lock();
                log.debug("读数据。。。");
                TimeUnit.SECONDS.sleep(1);
                return data;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                log.debug("释放写锁。。。");
                w.unlock();
            }
        } finally {
            log.debug("释放读锁。。。");
            r.unlock();
        }
    }
}
